/* Copyright (c) 2022-2025 Qualcomm Technologies International, Ltd. */
/* %%version */

#include "csr_synergy.h"

#ifndef EXCLUDE_GATT_XPAN_CLIENT_MODULE

#include <string.h>
#include <service_handle.h>
#include "csr_pmem.h"
#include "gatt_lib.h"

#include "gatt_xpan_client.h"
#include "gatt_xpan_client_common.h"
#include "gatt_xpan_client_msg_handler.h"
#include "gatt_xpan_client_init.h"
#include "gatt_xpan_client_private.h"
#include "gatt_xpan_client_debug.h"


gatt_xpan_client *xpanClientMain;

static bool gattRegisterXpanClient(gatt_xpan_client_registration_params_t *regParam, GXPANC *gattXpanClient)
{
    CsrBtTypedAddr addr;

    gattXpanClient->srvcElem->gattId = CsrBtGattRegister(GATT_XPAN_CLIENT_IFACEQUEUE);

    if (gattXpanClient->srvcElem->gattId != CSR_BT_GATT_INVALID_GATT_ID)
    {
        if (CsrBtGattClientUtilFindAddrByConnId(regParam->cid,
                                                &addr))
        {
            CsrBtGattClientRegisterServiceReqSend(gattXpanClient->srvcElem->gattId,
                                                  regParam->start_handle,
                                                  regParam->end_handle,
                                                  addr);
            return TRUE;
        }
    }
    
	return FALSE;
}

/******************************************************************************/
void gattXpanClientSendInitCfm(GXPANC *gatt_xpan_client,
                                GattXpanClientStatus status)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientInitCfm);
    
    if (status == GATT_XPAN_CLIENT_STATUS_SUCCESS)
    {
        message->clntHndl = gatt_xpan_client->srvcElem->service_handle;
    }
    else
    {
        message->clntHndl = 0;
    }

    message->cid = gatt_xpan_client->srvcElem->cid;

    message->status = status;
    
    XpanClientMessageSend(gatt_xpan_client->app_task, GATT_XPAN_CLIENT_INIT_CFM, message);
}

static void initXpanClientServiceHandleList(CsrCmnListElm_t *elem)
{
    /* Initialize a Service Handle list element. This function is called every
     * time a new entry is made on the queue list */
    ServiceHandleListElm_t *cElem = (ServiceHandleListElm_t *) elem;

    cElem->service_handle = 0;
}

/****************************************************************************/
void GattXpanClientInitReq(AppTask theAppTask,
                           const GattXpanClientInitData   *const initData,
                           const GattXpanClientDeviceData *deviceData)
{
    GXPANC * client = NULL;
    gatt_xpan_client_registration_params_t registration_params;
    ServiceHandle clientHandle = 0;
    
    if (theAppTask == CSR_SCHED_QID_INVALID)
    {
        GATT_XPAN_CLIENT_PANIC("GattXpanClientInitReq: Application Task Invalid \n");
        return;
    }

    if (initData == NULL)
    {
        GATT_XPAN_CLIENT_PANIC("Invalid initialization parameters\n");
        return;
    }

    if(xpanClientMain == NULL)
    {
        GATT_XPAN_CLIENT_PANIC("GattXpanClientInitReq: XPAN not initialized \n");
        return;
    }
    
    clientHandle = ServiceHandleNewInstance((void **)&client, sizeof(GXPANC));


    GATT_XPAN_CLIENT_INFO("Xpan:  GattXpanClientInit\n\n");

    if (client)
    {
        ServiceHandleListElm_t *elem = XPAN_ADD_SERVICE_HANDLE(xpanClientMain->serviceHandleList);

        elem->service_handle = clientHandle;
        client->srvcElem = elem;

        memset(&registration_params, 0, sizeof(gatt_xpan_client_registration_params_t));

        /* Store the Task function parameter.
           All library messages need to be sent here */
        client->app_task = theAppTask;

        client->clientData.startHandle = initData->startHandle;
        client->clientData.endHandle = initData->endHandle;
        client->srvcElem->cid = initData->cid;
        client->srvcElem->service_handle = clientHandle;
        client->clientDataIsSet = FALSE;

        if (deviceData)
        {
            memcpy(&(client->handles), deviceData, sizeof(GattXpanClientDeviceData));
        }
        else
        {
            memset(&(client->handles), 0, sizeof(GattXpanClientDeviceData));
        }

        client->pending_handle = 0;
        client->pending_cmd = 0;

        /* Setup data required for Gatt Client to be registered with the GATT Manager */
        registration_params.cid = initData->cid;
        registration_params.start_handle = initData->startHandle;
        registration_params.end_handle = initData->endHandle;

        /* Register Client to GATT */
        if (gattRegisterXpanClient(&registration_params, client))
        {
            if (deviceData)
            {
                SynMemCpyS(&client->handles, sizeof(GattXpanClientDeviceData),
                           deviceData, sizeof(GattXpanClientDeviceData));

                gattXpanClientSendInitCfm(client, GATT_XPAN_CLIENT_STATUS_SUCCESS);
                client->clientDataIsSet = TRUE;
            }
        }
        else
        {
            GATT_XPAN_CLIENT_ERROR("Register with the GATT failed!\n");
            gattXpanClientSendInitCfm(client, GATT_XPAN_CLIENT_STATUS_FAILED);
        }
    }
    else
    {
        MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientInitCfm);

        message->clntHndl = 0;
        message->cid = initData->cid;
        message->status = GATT_XPAN_CLIENT_STATUS_FAILED;

        XpanClientMessageSend(theAppTask, GATT_XPAN_CLIENT_INIT_CFM, message);
    }
}

void GattXpanClientInit(void **gash)
{
    xpanClientMain = CsrPmemZalloc(sizeof(*xpanClientMain));
    *gash          = xpanClientMain;

    CsrCmnListInit(&xpanClientMain->serviceHandleList,
                   0,
                   initXpanClientServiceHandleList,
                   NULL);
				   
	/* Set up library handler for external messages */
    xpanClientMain->lib_task = GATT_XPAN_CLIENT_IFACEQUEUE;
}

#ifdef ENABLE_SHUTDOWN
void GattXpanClientDeInit(void **gash)
{
    CsrCmnListDeinit(&xpanClientMain->serviceHandleList);
    CsrPmemFree(xpanClientMain);
	xpanClientMain = NULL;
}
#endif
#endif /* EXCLUDE_GATT_XPAN_CLIENT_MODULE */